/**
 * Title: Hyperbolic engine
 * Description: jFamilyTree Engine
 * Version: provider
 * Copyright: (c) 2001-2008
 * Terms of use:see license agreement at http://treebolic.sourceforge.net/en/license.htm
 * Author: Bernard Bou
 * Company: bsys
 * Update: Mon Mar 10 00:00:00 CEST 2008
 */
package jFamilyTree.view;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.util.List;

import jFamilyTree.model.IEdge;
import jFamilyTree.model.INode;

/**
 * Painter base class
 * 
 * @author Bernard Bou
 */
public abstract class AbstractPainter extends Mapper
{
	// S T A T I C . F I N A L . D A T A

	// font
	/**
	 * Number of font sizes
	 */
	static protected final int NFONTS = 6;

	/**
	 * Font default size
	 */
	static private final int FONTDEFAULTSIZE = 16;

	/**
	 * Font size increment/decrement step
	 */
	static private final int FONTDEFAULTSTEP = 1;

	// insets
	/**
	 * x inset for node box
	 */
	static protected final int theXInset = 4;

	/**
	 * y inset for node box
	 */
	static protected final int theYInset = 4;

	// colors
	/**
	 * Initial default background color
	 */
	static private final Color theBackColor0 = Color.WHITE;

	/**
	 * Initial default foreground color
	 */
	static private final Color theForeColor0 = Color.BLACK;

	/**
	 * Initial default node background color
	 */
	static private final Color theNodeBackColor0 = Color.WHITE;

	/**
	 * Initial default node foreground color
	 */
	static private final Color theNodeForeColor0 = Color.BLACK;

	/**
	 * Initial default tree edge color
	 */
	static private final Color theTreeEdgeColor0 = Color.BLACK;

	/**
	 * Initial default tree edge color
	 */
	static private final Color theEdgeColor0 = Color.RED;

	// D A T A

	// graphics context
	/**
	 * Cached graphics context
	 */
	protected Graphics theGraphics;

	// state
	/**
	 * Whether a dragging operation is pending
	 */
	protected boolean isDragging = false;

	// arcs
	/**
	 * Whether to render edges as hyperbolic edges
	 */
	protected boolean hyperbolicEdges = true;

	// fonts
	/**
	 * Fonts
	 */
	protected Font theFonts[] = new Font[NFONTS];

	// colors
	/**
	 * Default background color
	 */
	protected Color theBackColor;

	/**
	 * Default foreground color
	 */
	protected Color theForeColor;

	/**
	 * Default node background color
	 */
	protected Color theNodeBackColor;

	/**
	 * Default node foreground color
	 */
	protected Color theNodeForeColor;

	/**
	 * Default tree edge color
	 */
	protected Color theTreeEdgeColor;

	/**
	 * Default edge color
	 */
	protected Color theEdgeColor;

	// styles
	/**
	 * Default tree edge style
	 */
	protected int theTreeEdgeStyle;

	/**
	 * Default edge style
	 */
	protected int theEdgeStyle;

	// images
	/**
	 * Default node image
	 */
	public Image theDefaultNodeImage;

	/**
	 * Default tree edge image
	 */
	public Image theDefaultTreeEdgeImage;

	/**
	 * Default edge image
	 */
	public Image theDefaultEdgeImage;

	/**
	 * Background (tiled) image
	 */
	public Image theBackgroundImage;

	// C O N S T R U C T O R

	/**
	 * Constructor
	 */
	public AbstractPainter()
	{
	}

	// P A I N T

	/**
	 * Paint background
	 */
	public abstract void paintBackground();

	/**
	 * Paint
	 * 
	 * @param thisRoot
	 *        starting node
	 * @param thisEdgeList
	 *        edges
	 */
	public abstract void paint(INode thisRoot, List<IEdge> thisEdgeList);

	// S E T U P

	/**
	 * Set up graphics context for the painter to work on
	 * 
	 * @param thisGraphics
	 *        graphics context to work on
	 * @param thisSize
	 *        size of the graphics context
	 */
	public void setup(Graphics thisGraphics, Dimension thisSize)
	{
		theGraphics = thisGraphics;
		theSize = thisSize;
		theTop = -thisSize.height / 2;
		theLeft = -thisSize.width / 2;

		// translation
		theGraphics.translate(-theLeft, -theTop);

		// scale
		computeScale();
	}

	// F O N T S

	/**
	 * Set fonts
	 * 
	 * @param thisFontFace
	 *        font
	 * @param thisFontSize
	 *        font size
	 * @param thisFontSizeStep
	 *        font size increment/decrement step
	 */
	public void setFonts(String thisFontFace, Integer thisFontSize, Integer thisFontSizeStep)
	{
		if (thisFontFace == null)
			thisFontFace = "SansSerif";
		if (thisFontSize == null)
			thisFontSize = FONTDEFAULTSIZE;
		if (thisFontSizeStep == null)
			thisFontSizeStep = FONTDEFAULTSTEP;
		for (int i = 0; i < NFONTS; i++)
			theFonts[i] = new Font(thisFontFace, Font.PLAIN, thisFontSize - i * thisFontSizeStep);
	}

	// C O L O R S

	/**
	 * Set colors
	 * 
	 * @param thisBackColor
	 *        background default color
	 * @param thisForeColor
	 *        foreground default color
	 * @param thisNodeBackColor
	 *        node background default color
	 * @param thisNodeForeColor
	 *        node foreground default color
	 * @param thisTreeEdgeColor
	 *        tree edge default color
	 * @param thisEdgeColor
	 *        edge default color
	 */
	public void setColors(Color thisBackColor, Color thisForeColor, Color thisNodeBackColor, Color thisNodeForeColor, Color thisTreeEdgeColor, Color thisEdgeColor)
	{
		if (thisBackColor != null)
			theBackColor = thisBackColor;
		if (thisForeColor != null)
			theForeColor = thisForeColor;
		if (thisNodeBackColor != null)
			theNodeBackColor = thisNodeBackColor;
		if (thisNodeForeColor != null)
			theNodeForeColor = thisNodeForeColor;
		if (thisTreeEdgeColor != null)
			theTreeEdgeColor = thisTreeEdgeColor;
		if (thisEdgeColor != null)
			theEdgeColor = thisEdgeColor;
	}

	/**
	 * Reset colors
	 */
	public void resetColors()
	{
		theForeColor = theForeColor0;
		theBackColor = theBackColor0;
		theNodeBackColor = theNodeBackColor0;
		theNodeForeColor = theNodeForeColor0;
		theTreeEdgeColor = theTreeEdgeColor0;
		theEdgeColor = theEdgeColor0;
	}

	// S T Y L E S

	/**
	 * Set default edge styles
	 * 
	 * @param thisTreeEdgeStyle
	 *        default tree edge style
	 * @param thisEdgeStyle
	 *        default edge style
	 */
	public void setEdgeStyles(Integer thisTreeEdgeStyle, Integer thisEdgeStyle)
	{
		if (thisTreeEdgeStyle != null)
			theTreeEdgeStyle = thisTreeEdgeStyle;
		if (thisEdgeStyle != null)
			theEdgeStyle = thisEdgeStyle;
	}

	/**
	 * Set images
	 * 
	 * @param thisBackgroundImage
	 *        background image
	 * @param thisDefaultNodeImage
	 *        default node image
	 * @param thisDefaultTreeEdgeImage
	 *        default tree edge image
	 * @param thisDefaultEdgeImage
	 *        default edge image
	 */
	public void setImages(Image thisBackgroundImage, Image thisDefaultNodeImage, Image thisDefaultTreeEdgeImage, Image thisDefaultEdgeImage)
	{
		theBackgroundImage = thisBackgroundImage;
		theDefaultNodeImage = thisDefaultNodeImage;
		theDefaultTreeEdgeImage = thisDefaultTreeEdgeImage;
		theDefaultEdgeImage = thisDefaultEdgeImage;
	}

	// B E H A V I O U R

	/**
	 * Set edge rendering mode
	 * 
	 * @param thisFlag
	 *        true if edges are rendered as arcs
	 */
	public void setHyperbolicEdges(Boolean thisFlag)
	{
		if (thisFlag != null)
			hyperbolicEdges = thisFlag;
	}

	/**
	 * Get edge rendering mode
	 * 
	 * @return true if edges are rendered as arcs
	 */
	public boolean getHyperbolicEdges()
	{
		return hyperbolicEdges;
	}

	// E V E N T

	/**
	 * Enter drag mode
	 */
	public void enterDrag()
	{
		isDragging = true;
	}

	/**
	 * Leave drag mode
	 */
	public void leaveDrag()
	{
		isDragging = false;
	}
}
